package cc.rengu.igas.bsps.core.packswitch;

import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.constant.BspsTreeNodeConstant;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.model.UserSessionInfo;
import cc.rengu.jradp.packetswitch.IncomingPackSwitchImpl;
import cc.rengu.jradp.packetswitch.OutgoingPackSwitchImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.PayOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.PayOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.PayOrderInfo;
import cc.rengu.oltp.service.common.entity.SysParam;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.TxnInfo;
import cc.rengu.oltp.service.realize.SysParamService;
import cc.rengu.oltp.service.realize.TxnInfoService;
import cc.rengu.oltp.service.realize.impl.SysParamServiceImpl;
import cc.rengu.oltp.service.realize.impl.TxnInfoServiceImpl;
import cc.rengu.oltp.utility.util.*;
import cc.rengu.utility.log.RgLog;
import cc.rengu.utility.log.RgLogger;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import org.apache.commons.codec.binary.Base64;

import java.io.File;
import java.io.FileInputStream;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 与商户服务APP通讯层报文解包前后、组前包后实现类
 */
public class MchntAppServerPackSwitch implements IncomingPackSwitchImpl, OutgoingPackSwitchImpl {

    @Override
    public byte[] beforeInComPackSwitch(byte[] bytes) throws Exception {
        RgLogger rglog = RgLog.getLogger(this.getClass().getName());
        String jsonStr = new String(bytes);
        /* 转换XSS攻击的字符 */
        jsonStr = jsonStr.replaceAll("<", "＜").replaceAll(">", "＞");
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        /*GET请求处理*/
        String method = xmlTreeUtil.getXmlTreeStringValue("_MESSAGEHEAD/http/method");
        rglog.debug("请求方式:<{}>", method);
        if ("GET".equals(method)) {
            String serverUrl = xmlTreeUtil.getXmlTreeStringValue("_MESSAGEHEAD/@server_url");
            rglog.debug("serverUrl:<{}>", serverUrl);
            /*get请求特殊处理*/
            String[] serverUrls = serverUrl.split("\\?");
            if (serverUrls.length < 2) {
                rglog.error("请求非法");
                return null;
            }
            serverUrl = serverUrls[1];
            serverUrl = URLDecoder.decode(serverUrl, "UTF-8");
            jsonStr = serverUrl.replaceAll(" ", "").replaceAll("\\n", "");
            rglog.debug("入参报文:<{}>", jsonStr);
            xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.IS_GET_REQUEST, "Y");
        }
        /*健康检查*/
        String healthChekUrl = xmlTreeUtil.getXmlTreeStringValue("_MESSAGEHEAD/@server_url");
        if (!StringUtil.isEmptyOrNull(healthChekUrl) && (healthChekUrl.contains("healthCheck") || healthChekUrl.contains("nginx.html"))) {
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_INST_ID, AppParamConstant.DEFAULT_INSTID);
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_SRC_SYS_ID, "NGINX");
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "HEALCHTK");
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, AppParamConstant.DEFAULT_BIZ_TYPE);
            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_CHANNEL_ID, "NGINX");
            return "{}".getBytes();
        } else {
            //获取验签串
            String signBlockString = generateSignBlockString(jsonStr);
            xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.SIGN_BLOCK, signBlockString);
        }
        return jsonStr.getBytes();
    }

    @Override
    public int afterInComPackSwitch() throws Exception {
        RgLogger rglog = RgLog.getLogger(this.getClass().getName());
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        String instId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_INST_ID);
        String txnNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM);
        String bizType = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE);
        String mchntNo = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.MCHNT_NO);

        /* 获取交易配置信息 */
        TxnInfoService txnInfoService = new TxnInfoServiceImpl();
        TxnInfo txnInfo = txnInfoService.getCurrentTxnInfo();
        xmlTreeUtil.setXmlTreeObjectValue(TreeNodeConstant.TXN_INFO,txnInfo);

        /* 判断是否要验签 */
        xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.VERIFY_SIGN_FLAG, AppParamConstant.YES);
        if (AppParamConstant.YES.equals(txnInfo.getSrcTxnAuthCfg().getSignFlag())) {
            String signBlockString = xmlTreeUtil.getXmlTreeStringValue(BspsTreeNodeConstant.SIGN_BLOCK);
            String signature = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_SIGNATURE);
            /*查询redis获取签名密钥*/
            String sessionId = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.HEADER_SESSION);
            if (sessionId == null || "".equals(sessionId.trim())) {
                rglog.error("会话标识sessionId为null");
                xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.VERIFY_SIGN_FLAG, AppParamConstant.NO);
                return 0;
            }
            String sessionObjStr = RedisUtil.onceGet(sessionId);
            if (sessionObjStr == null) {
                rglog.error("根据会话标识<{}>获取会话缓存失败", sessionId);
                xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.VERIFY_SIGN_FLAG, AppParamConstant.NO);
            }

            UserSessionInfo userSessionInfo = JSON.parseObject(sessionObjStr, UserSessionInfo.class);
            if (null == userSessionInfo) {
                rglog.error("根据会话标识<{}>获取会话缓存失败，转为UserSessionInfo失败。", sessionId);
                xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.VERIFY_SIGN_FLAG, AppParamConstant.NO);
                return 0;
            }
            xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.SIGN_KEY, userSessionInfo.getSignatureKey());
            SysParamService sysParamService = new SysParamServiceImpl();
            SysParam signBlockParam = sysParamService.getSysParamInfo(instId, BspsAppParamConstant.MCHNT_PARAM_TYPE, BspsAppParamConstant.SIGN_BLOCK_PARAM);
            if (null != signBlockParam && "N".equals(signBlockParam.getParamValue())) {
                rglog.info("不验签");
                xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.VERIFY_SIGN_FLAG, AppParamConstant.YES);
            } else {
                rglog.info("验签交易");
                rglog.info("验签key：" + userSessionInfo.getSignatureKey());
                if (!MD5Util.verifySignString(signature, signBlockString, "&key=", userSessionInfo.getSignatureKey())) {
                    rglog.error("验签失败!sign:<{}>，signBlock:<{}>", signature, signBlockString);
                    xmlTreeUtil.setXmlTreeStringValue(BspsTreeNodeConstant.VERIFY_SIGN_FLAG, AppParamConstant.NO);
                }
            }
        }


        /*普通退款交易特殊处理*/
        if (BspsAppParamConstant.REFUND_PUB_TXN_NUM.equals(txnNum) && AppParamConstant.DEFAULT_BIZ_TYPE.equals(bizType)) {
            xmlTreeUtil.setXmlTreeStringValue("BSPS_REFUND_TXN_NUM", txnNum);
            xmlTreeUtil.setXmlTreeStringValue("BSPS_BIZ_TYPE", bizType);
            String origSysSeqNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.ORIG_SYS_SEQ_NUM);
            /*根据商户号、流水号查询原支付交易*/
            MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
            MchntOrderInfo mchntOrderInfo = mchntOrderInfoMapper.selectMchntOrderInfoByPrimaryKey(instId, origSysSeqNum, mchntNo);
            if (mchntOrderInfo == null) {
                rglog.info("商户订单信息表中无该笔订单,instId:<{}>,sysSeqNum:<{}>.不转换交易码", instId, origSysSeqNum);
                return 0;
            }
            /*转换交易码*/
            if ("P01PM003".equals(mchntOrderInfo.getTxnNum()) || "P01MC003".equals(mchntOrderInfo.getTxnNum())) {
                /*主扫支付*/
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "P04BS001");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "P04BS001");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, mchntOrderInfo.getBizType());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, mchntOrderInfo.getBizType());
            } else if ("P01BS002".equals(mchntOrderInfo.getTxnNum()) || "P01MC006".equals(mchntOrderInfo.getTxnNum())) {
                /*被扫支付*/
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "P04BS002");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "P04BS002");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, mchntOrderInfo.getBizType());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, mchntOrderInfo.getBizType());
            } else if ("P01PM002".equals(mchntOrderInfo.getTxnNum())) {
                /*微信支付*/
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "P04BS003");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "P04BS003");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, mchntOrderInfo.getBizType());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, mchntOrderInfo.getBizType());
            } else if ("P01PM004".equals(mchntOrderInfo.getTxnNum()) ||
                    "P01PM001".equals(mchntOrderInfo.getTxnNum()) ||
                    "P01PM011".equals(mchntOrderInfo.getTxnNum()) ||
                    "P01PM013".equals(mchntOrderInfo.getTxnNum())) {
                /*银行卡快捷支付*/
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "P04BS004");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "P04BS004");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, mchntOrderInfo.getBizType());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, mchntOrderInfo.getBizType());
                if ("P01PM001".equals(mchntOrderInfo.getTxnNum()) || "P01PM011".equals(mchntOrderInfo.getTxnNum())) {
                    /*新卡支付、首次签约支付*/

                    /*获取支付订单列表*/
                    PayOrderInfoMapper payOrderInfoMapper = new PayOrderInfoMapperImpl();
                    List<PayOrderInfo> payOrderInfoList = payOrderInfoMapper.selectPayOrderInfoBySysSeqNum(instId, mchntOrderInfo.getSysSeqNum());
                    if (payOrderInfoList == null || payOrderInfoList.size() == 0) {
                        rglog.error("根据机构号<{}>、系统流水号<{}>获取支付订单列表失败", instId, mchntOrderInfo.getSysSeqNum());
                    } else {
                        List<PayOrderInfo> payOrderInfoListNcqs = payOrderInfoList.stream().filter(item -> item.getMsgDstId().equals(ChannelEnum.NCQS.getChannelType())).collect(Collectors.toList());
                        List<PayOrderInfo> payOrderInfoListUpac = payOrderInfoList.stream().filter(item -> item.getMsgDstId().equals(ChannelEnum.UPAC.getChannelType())).collect(Collectors.toList());
                        if (payOrderInfoListNcqs != null && !payOrderInfoListNcqs.isEmpty()) {
                            /*无卡快捷*/
                            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, "02");
                            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, "02");
                        } else if (payOrderInfoListUpac != null && !payOrderInfoListUpac.isEmpty()) {
                            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, "01");
                            xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, "01");
                        }
                    }
                } else if ("P01PM013".equals(mchntOrderInfo.getTxnNum())) {
                    xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, "01");
                    xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, "01");
                }
            } else if ("P01PM007".equals(mchntOrderInfo.getTxnNum())) {
                /*网关支付*/
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "P04BS005");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "P04BS005");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, mchntOrderInfo.getBizType());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, mchntOrderInfo.getBizType());
            } else if ("P01PM005".equals(mchntOrderInfo.getTxnNum())) {
                /*手机银行sdk支付*/
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "P04BS007");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "P04BS007");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, mchntOrderInfo.getBizType());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, mchntOrderInfo.getBizType());
            } else if ("P01PM006".equals(mchntOrderInfo.getTxnNum())) {
                /*云闪付支付*/
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "P04BS008");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "P04BS008");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, mchntOrderInfo.getBizType());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, mchntOrderInfo.getBizType());
            } else if ("P01PM008".equals(mchntOrderInfo.getTxnNum())) {
                /*纯积分支付*/
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "P04BS009");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "P04BS009");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, mchntOrderInfo.getBizType());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, mchntOrderInfo.getBizType());
            } else if ("P01PM009".equals(mchntOrderInfo.getTxnNum())) {
                /*银行卡+积分支付*/
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.TXN_NUM, "P04BS010");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_TXN_NUM, "P04BS010");
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.BIZ_TYPE, mchntOrderInfo.getBizType());
                xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.HEADER_BIZ_TYPE, mchntOrderInfo.getBizType());
            } else {
                rglog.info("交易码<{}>不支持,不转换交易码", mchntOrderInfo.getTxnNum());
                return -1;
            }

        }
        return 0;
    }

    @Override
    public int beforeOutgoPackSwitch() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        if (xmlTreeUtil.isExist("BSPS_REFUND_TXN_NUM")) {
            xmlTreeUtil.copyStringValue("BSPS_REFUND_TXN_NUM", TreeNodeConstant.TXN_NUM);
            xmlTreeUtil.copyStringValue("BSPS_REFUND_TXN_NUM", TreeNodeConstant.HEADER_TXN_NUM);
        }
        if (xmlTreeUtil.isExist("BSPS_BIZ_TYPE")) {
            xmlTreeUtil.copyStringValue("BSPS_BIZ_TYPE", TreeNodeConstant.BIZ_TYPE);
            xmlTreeUtil.copyStringValue("BSPS_BIZ_TYPE", TreeNodeConstant.HEADER_BIZ_TYPE);
        }
        return 0;
    }

    @Override
    public byte[] afterOutgoPackSwitch(byte[] bytes) throws Exception {
        RgLogger rglog = RgLog.getLogger(this.getClass().getName());
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/Content-Type", "application/json;charset=utf-8");
        xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/ArgList", "Content-Type");
        String txnNum = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TXN_NUM);
        TxnInfo txnInfo = (TxnInfo) xmlTreeUtil.getXmlTreeObjectValue(TreeNodeConstant.TXN_INFO, TxnInfo.class);
        if (null == txnInfo) {
            TxnInfoService txnInfoService = new TxnInfoServiceImpl();
            txnInfo = txnInfoService.getCurrentTxnInfo();
        }

        /*对账单下载特殊处理*/
        String respCode = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.RESP_CODE);
        String isGetRequest = xmlTreeUtil.getXmlTreeStringValue(BspsTreeNodeConstant.IS_GET_REQUEST);
        if ((("T00BS027".equals(txnNum) || ("T00BS105".equals(txnNum))) && "Y".equals(isGetRequest))) {
            if (RespCodeEnum.TRANS_SUCCESS.getRespCode().equals(respCode)) {
                //成功时处理
                String filePath = xmlTreeUtil.getXmlTreeStringValue(BspsTreeNodeConstant.RECON_DETAIL_PATH);
                File file = new File(filePath);
                if (!file.exists()) {
                    rglog.error("文件<{}>不存在!", filePath);
                    xmlTreeUtil.setXmlTreeIntValue("_MESSAGEHEAD/@server_ret", 500);
                    return "文件不存在!".getBytes();
                }

                String fileName = file.getName();
                String fileType = fileName.split("\\.")[1];
                if ("csv".equals(fileType)) {
                    xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/Content-Type", "text/csv;charset=GBK;download");
                } else {
                    xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/Content-Type", "application/vnd.ms-excel");
                }

                xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/Content-Length", String.valueOf(file.length()));
                xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/Content-Disposition", "attachment;filename=" + file.getName());
                xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/http/ArgList", "Content-Type:Content-Disposition");

                //IO流操作
                FileInputStream fileInputStream = null;
                byte[] downloadFileBytes = null;
                try {
                    fileInputStream = new FileInputStream(file);
                    downloadFileBytes = new byte[fileInputStream.available()];
                    fileInputStream.read(downloadFileBytes);
                } catch (Exception e) {
                    rglog.error(e.getMessage());
                } finally {
                    //关闭流
                    try {
                        if (null != fileInputStream) {
                            fileInputStream.close();
                        }
                    } catch (Exception e) {
                        rglog.error(e.getMessage());
                    }
                }
                if (("T00BS105".equals(txnNum))) {
                    file.delete();
                }

                return downloadFileBytes;
            } else {
                //失败时处理
                xmlTreeUtil.setXmlTreeStringValue("_MESSAGEHEAD/@server_ret", "500");
                String respDesc = xmlTreeUtil.getXmlTreeStringValue("respDesc");
                if (StringUtil.isEmptyOrNull(respDesc)) {
                    respDesc = xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.RESP_DESC);
                }
                rglog.debug("错误信息code<{}>,msg<{}>", respCode, respDesc);
                if (StringUtil.isEmptyOrNull(respDesc)) {
                    return new byte[0];
                } else {
                    return respDesc.getBytes();
                }
            }
        }

        if (txnInfo.getSrcTxnAuthCfg().getTxnNum().equals("HEALCHTK")) {
            return new byte[0];
        }

        if (AppParamConstant.NO.equals(txnInfo.getSrcTxnAuthCfg().getSignFlag())) {
            return bytes;
        }

        String jsonBefore = new String(bytes);
        String signBlock = generateSignBlockString(jsonBefore);
        /* 生成生成数字签名的字符串 */
        if (null == signBlock) {
            rglog.error("生成加签Block失败!");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        rglog.debug("加签Block:<{}>", signBlock);

        String md5Key = xmlTreeUtil.getXmlTreeStringValue(BspsTreeNodeConstant.SIGN_KEY);
        String signData = MD5Util.generateSignString(signBlock, "&key=", md5Key);
        if (null == signData) {
            rglog.error("生成数字签名失败!");
            throw new BizException(RespCodeEnum.GENERATE_SIGN_ERROR.getRespCode(), RespCodeEnum.GENERATE_SIGN_ERROR.getRespDesc());
        }
        rglog.debug("数字签名:<{}>", signData);

        JSONObject jsonObj = JSON.parseObject(jsonBefore, Feature.OrderedField);
        JSONObject headObj = jsonObj.getJSONObject(BspsTreeNodeConstant.HEADER);
        headObj.put(BspsTreeNodeConstant.SIGNATURE, signData);
        jsonObj.put(BspsTreeNodeConstant.HEADER, headObj);
        rglog.debug("添加signature后发送报文:<{}>", jsonObj.toJSONString());
        return jsonObj.toJSONString().getBytes();
    }

    /**
     * 生成加签Block
     *
     * @param jsonString 原始报文
     * @return 加签BLOCK
     */
    private String generateSignBlockString(String jsonString) {
        RgLogger rglog = RgLog.getLogger(this.getClass().getName());
        try {
            if (null != jsonString && 0 != jsonString.trim().length()) {
                rglog.debug("jsonString=[{}]", jsonString);
                JSONObject jsonObject = JSONObject.parseObject(jsonString, Feature.OrderedField);
                ArrayList<String> arrayList = new ArrayList<>();
                Map maps = jsonObject.getInnerMap();
                int i = 0;
                Object key;
                Object value;
                for (Object map : maps.entrySet()) {
                    key = ((Map.Entry) map).getKey();
                    value = ((Map.Entry) map).getValue();
                    if (!BspsTreeNodeConstant.HEADER.equals(key) && null != value) {
                        arrayList.add(key + "=" + value + "&");
                    } else if (BspsTreeNodeConstant.HEADER.equals(key) && null != value) {
                        JSONObject headObj = JSONObject.parseObject(value.toString(), Feature.OrderedField);
                        headObj.remove(BspsTreeNodeConstant.SIGNATURE);
                        arrayList.add(key + "=" + headObj + "&");
                    }
                    i++;
                }
                String[] strArray = arrayList.toArray(new String[arrayList.size()]);
                Arrays.sort(strArray);
                StringBuffer stringBuffer = new StringBuffer();
                for (i = 0; i < strArray.length; i++) {
                    stringBuffer.append(strArray[i]);
                }
                return stringBuffer.substring(0, stringBuffer.length() - 1).toString();
            }
        } catch (Exception e) {
            rglog.error("系统异常!");
            return null;
        }
        return null;
    }

    String encryptData(String keyValue, String encData) throws Exception {
        RgLogger rglog = RgLog.getLogger(this.getClass().getName());

        byte[] bEncData = encData.getBytes();
        int round = bEncData.length / 16;
        if (bEncData.length % 16 != 0) {
            round = round + 1;
        }
        byte[] srcBData = new byte[round * 16];
        if (bEncData.length % 16 == 0) {
            srcBData = bEncData;
        } else {
            System.arraycopy(bEncData, 0, srcBData, 0, bEncData.length);
            for (int i = bEncData.length; i < round * 16; i++) {
                srcBData[i] = 0;
            }

        }
        byte[] descData = new byte[srcBData.length];
        int retCode = SM4Util.sms4(srcBData, srcBData.length, ByteUtil.hexStringToByte(keyValue), descData, 1);
        if (retCode == 0) {
            return Base64.encodeBase64String(descData);
        }
        return null;
    }
}
